﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Farigola.Engine.SystemData.Entity.Type;
using Farigola.Engine.SystemData.DataValue;

namespace Farigola.Engine.SystemData.Entity.inst
{
    /// <summary>
    /// Entity instance structure list of entities instances or data values!.
    /// Its a specific entity instance, its a container, can contain data values or entities instances.
    /// </summary>
    public class EntInstStructList : EntInstStructureBase
    {
        //=====================================================================
        #region Private/protected data members.

        /// <summary>
        /// The typeOfInst of the list.
        /// todo: remove it.
        /// </summary>
        //private EntTypeStructList _entTypeStructList;

        /// <summary>
        /// Inst access mode of items.
        /// </summary>
        //private EntTypeInstanceAccessMode _instAccessModeOfItems = EdObTypeInstanceAccessMode.NewInstanceNotNull;

        /// <summary>
        /// Type of items in the list, if its data values.
        /// </summary>
        private DataValueType _dataValueTypeItems = DataValueType.Undefined;

        /// <summary>
        /// Type of items in the list, if its entities.
        /// </summary>
        private EntTypeBase _entTypeBaseItems=null;

        /// <summary>
        /// // list of items instance of the list, if its entities.
        /// acn't contains entity type, only entity instance.
        /// </summary>
        private List<EntInstBase> _listEntInstItems = null;

        private List<DataValueBase> _listDataValueItems= null;

        #endregion

        //=====================================================================
        #region Public Properties.

        //public EdObTypeInstanceAccessMode InstAccessModeOfItems
        //{
        //    get
        //    {
        //        return _instAccessModeOfItems;
        //    }
        //}

        /// <summary>
        /// Type of items in the list, return null if list contains data values.
        /// </summary>
        public EntTypeBase EntTypeBaseItems
        {
            get { return _entTypeBaseItems; }
        }

        /// <summary>
        /// Type of items in the list, return null if list contains entities.
        /// </summary>
        public DataValueType DataValueTypeItems
        {
            get { return _dataValueTypeItems; }
        }

        /// <summary>
        /// get list of items instance,
        /// return the original list of items (ref to items).
        /// </summary>
        public List<EntInstBase> ListEntInstItems
        {
            get { return _listEntInstItems; }
        }

        /// <summary>
        /// get list of items instance,
        /// return the original list of items (ref to items).
        /// </summary>
        public List<DataValueBase> ListDataValueItems
        {
            get { return _listDataValueItems; }
        }

        public bool IsDataValueTypeItems
        {
            get { 
                if(_dataValueTypeItems != DataValueType.Undefined)
                    return true;
                return false;
            }
        }

        public bool IsEntTypeBaseItems
        {
            get
            {
                if (_entTypeBaseItems != null)
                    return true;
                return false;
            }
        }

        public int Count 
        {
            get
            {
                if (IsDataValueTypeItems) 
                    return _listDataValueItems.Count;
                return _listEntInstItems.Count;
            }
        }
        #endregion

        //=====================================================================
        #region Constructors.

        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="systOrUser"></param>
        /// <param name="id"></param>
        /// <param name="name"></param>
        public EntInstStructList(EntityDef.TypeSystOrUser systOrUser, DataValueType dataValueTypeItems, EntityId id, String name)
            : base(systOrUser, id, name)
        {
            InitDataValue(dataValueTypeItems);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="systOrUser"></param>
        /// <param name="id"></param>
        /// <param name="name"></param>
        public EntInstStructList(EntityDef.TypeSystOrUser systOrUser, EntTypeBase entTypeItems, EntityId id, String name)
            : base(systOrUser, id, name)
        {
            InitEntType(entTypeItems);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        public EntInstStructList(DataValueType dataValueTypeItems, EntityId id, String name)
            : base(id, name)
        {
            InitDataValue(dataValueTypeItems);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        public EntInstStructList(EntTypeBase entTypeItems, EntityId id, String name)
            : base(id, name)
        {
            InitEntType(entTypeItems);
        }

        #endregion

        //=====================================================================
        #region Init methods.

        //---------------------------------------------------------------------
        protected void InitEntType(EntTypeBase entTypeBaseItems)
        {
            _entTypeBaseItems = entTypeBaseItems;
            _listEntInstItems = new List<EntInstBase>();
        }

        //---------------------------------------------------------------------
        protected void InitDataValue(DataValueType dataValueTypeItems)
        {
            _dataValueTypeItems = dataValueTypeItems;
            _listDataValueItems = new List<DataValueBase>();
        }
        #endregion

        

        //=====================================================================
        #region Public Set/get methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// set the typeOfInst of items listed
        /// </summary>
        /// <param newName="typeOfInst"></param>
        //public void SetEdObTypeBaseOfItems(EdObTypeInstanceAccessMode instAccessModeOfItems, EdObTypeBase type)
        //{
        //    _instAccessModeOfItems = instAccessModeOfItems;
        //    _edObTypeBaseOfItems = type;
        //}

        //---------------------------------------------------------------------
        /// <summary>
        /// Return the item instance at the specified position.
        /// 
        /// if not exists, return null.
        /// </summary>
        /// <param newName="pos"></param>
        /// <returns></returns>
        public EntInstBase GetEntInstItemAt(int pos)
        {
            if (_listEntInstItems == null)
                return null;

            // pos not valid or list is empty
            if (pos < 0 || pos >= _listEntInstItems.Count)
                return null;

            // ok return the value
            return _listEntInstItems[pos];
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Return the item data value at the specified position.
        /// 
        /// if not exists, return null.
        /// </summary>
        /// <param newName="pos"></param>
        /// <returns></returns>
        public DataValueBase GetDataValueItemAt(int pos)
        {
            if (_listDataValueItems== null)
                return null;

            // pos not valid or list is empty
            if (pos < 0 || pos >= _listDataValueItems.Count)
                return null;

            // ok return the value
            return _listDataValueItems[pos];
        }

        #endregion

        //=====================================================================
        #region Public Add methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Add a new item (an entity instance) in the list
        /// if not null and not already present.
        /// 
        /// return the count of items in the list.
        /// 
        /// </summary>
        /// <param newName="dataToBuildInstItem"></param>
        /// <returns></returns>
        public bool AddItem(EntInstBase item)
        {
            if (item == null)
                return false;
            if (_listEntInstItems == null)
                return false;

            // check if the item is not already present in the list
            if (_listEntInstItems.Contains(item))
                return false;

            // check the type of the item, must match with the type of list
            // todo:

            // add at end
            _listEntInstItems.Add(item);
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Add a new item data value in the list
        /// if not null and not already present.
        /// 
        /// return the count of items in the list.
        /// 
        /// </summary>
        /// <param newName="dataToBuildInstItem"></param>
        /// <returns></returns>
        public bool AddItem(DataValueBase item)
        {
            if (item == null)
                return false;
            if (_listDataValueItems == null)
                return false;

            // check if the item is not already present in the list
            if (_listDataValueItems.Contains(item))
                return false;

            // check the type of the data value
            if (item.DataValueType != _dataValueTypeItems)
                return false;

            // add at end
            _listDataValueItems.Add(item);
            return true;
        }

        #endregion

        //=====================================================================
        #region Public del/remove methods.

        // todo: removeAt(pos)
        // remove one item at position.

        //---------------------------------------------------------------------
        /// <summary>
        /// Remove all items of the list.
        /// </summary>
        /// <returns></returns>
        public bool RemoveAllItems()
        {
            if(_listEntInstItems != null)
                _listEntInstItems.Clear();
            if (_listDataValueItems != null)
                _listDataValueItems.Clear();
            return true;
        }

        #endregion
    }
}
